// 冒泡排序
/*
每次将相邻的两个进行比较，选出大的那个，一轮结束后就得到了数组中最大的元素
第二轮也是如此，重复次数-1，第二大的那个元素
说明：
比如有5个元素，我们只需要4趟就可以排好序，最后一个就是最小的 
也就是第一个for的趟数，就是循环的次数，我们只用循环arr.length-1次就可以了
当然了，遍历arr.length次也是可以的

第二个for循环控制的是每一趟的轮数
比如
第一轮的时候有5个元素，那我们就会从第一个元素开始与其它四个元素作比较，也就是会询问4次，选出最大的一个元素
第二轮的时候
*/
const bubblingSort = (arr) => {
  // 第一个for控制趟数，第二个for控制每一趟的次数
  for (let i = 1; i < arr.length; i++) {
    for (let j = 0; j < arr.length - i; j++) {
      if (arr[j] >= arr[j + 1]) {
        let temp = arr[j]
        arr[j] = arr[j + 1]
        arr[j + 1] = temp
      }
    }
  }
  return arr
}
// 选择排序 使用一个最小索引变量记住每一趟遍历比较中的最小值所处索引
// 优点:不用开辟额外的内存，复杂度一直都是O(n^2)
// 双重循环
// 我们可以理解为双指针，第一个指向每一趟的最小索引，第二个指针为前进指针
// 我们可以理解为动静指针

const selectSort = (arr) => {
  for (let i = 0; i < arr.length; i++) {
    // 初始化静指针默认指向第一个
    let minIndex = i
    // 动指针从索引为1处开始比较
    for (let j = i + 1; j < arr.length; j++) {
      // 如果动指针指向的内容比静指针小,那么就交换两个元素的位置
      if (arr[j] < arr[minIndex]) {
        minIndex = j
      }
    }
    [arr[i], arr[minIndex]] = [arr[minIndex], arr[i]]
  }
  return arr
}

// 插入排序
// 通过构建有序序列，对于未排序数据，在已排序序列中从后向前扫描，找到相应位置并插入
// 同样的可以使用两个指针，第一个指针指向已排序数组的最后一项，第二个指针指向未排序数组的第一项
// 也就是未排序指针的前一个是已排序指针
// 之后第一个指针从后向前移动，找到合适的位置插入
// 比如已排序 2356 未排序 4，第一个指针就会从后先前依次递减找到比4小的元素插入
const insertSort = (arr) => {
  if (!Array.isArray(arr) || arr.length < 2) return arr
  // 已排序指针默认指向第一个

  // 未排序的指针可以从索引为1处开始
  for (let unsort = 1; unsort < arr.length; unsort++) {
    let curValue = arr[unsort]
    let sorted = unsort - 1
    // 当符合条件时，也就是sorted指针存在并且 已排序指针指向的元素大于未排序指针指向的元素
    while (sorted >= 0 && curValue < arr[sorted]) {
      console.log(`sorted 是${sorted},arr[sorted]是${arr[sorted]},unsort是${unsort},arr[unsort]是${arr[unsort]},arr是${arr.toString()}`)
      arr[sorted + 1] = arr[sorted]
      sorted--
    }
    arr[sorted + 1] = curValue
  }
  return arr
}

// 快速排序
// 选一个参考值，比它大的放在它右边的数组，比它小的放在左边的数组
// 之后对左边和右边的数组执行同样的操作

function quickSort (arr) {
  if (arr.length <= 1) return arr
  // splice返回的是一个数组
  let midValue = arr.splice(Math.floor(arr.length / 2), 1)[0]
  let left = [], right = []
  arr.forEach(item => {
    if (item <= midValue) {
      left.push(item)
    }
    else {
      right.push(item)
    }
  })
  return quickSort(left).concat(midValue, quickSort(right))
}

function run (arr) {
  // console.log('冒泡排序的结果', bubblingSort(arr).toString())
  // console.log('选择排序的结果', selectSort(arr).toString())
  // console.log('插入排序的结果', insertSort(arr).toString())
  console.log('快速排序的结果', quickSort(arr).toString())
}
let arr = [4, 6, 7, 9, 2, 3, 4, 5, 0, 1]


run(arr)